const { readFile, writeFile } = require('fs/promises')

const OLD_REPORT = process.argv[2] ?? 'result_old/report.txt'
const NEW_REPORT = process.argv[3] ?? 'result/report.txt'

main(OLD_REPORT, NEW_REPORT)

async function main(path1, path2) {
    const file1 = await readFile(path1, 'utf8')
    const file2 = await readFile(path2, 'utf8')
    const report1 = parseReport(file1)
    const report2 = parseReport(file2)
    const progress = {}
    const regress = {}
    const fresh = {}
    const old = {}
    for (const [suiteName2, testsObj2] of Object.entries(report2)) {
        const testsObj1 = report1[suiteName2]
        if (testsObj1) {
            for (const passed of testsObj2.passed) {
                const passedIndex = testsObj1.passed.indexOf(passed)
                if (passedIndex >= 0) {
                    testsObj1.passed.splice(passedIndex, 1)
                } else {
                    const failedIndex = testsObj1.failed.indexOf(passed)
                    if (failedIndex >= 0) {
                        testsObj1.failed.splice(failedIndex, 1)
                        addToArray(progress, suiteName2, passed)
                    } else {
                        addToArray(fresh, suiteName2, passed)
                    }
                }
            }
            for (const failed of testsObj2.failed) {
                const failedIndex = testsObj1.failed.indexOf(failed)
                if (failedIndex >= 0) {
                    testsObj1.failed.splice(failedIndex, 1)
                } else {
                    const passedIndex = testsObj1.passed.indexOf(failed)
                    if (passedIndex >= 0) {
                        testsObj1.passed.splice(passedIndex, 1)
                        addToArray(regress, suiteName2, failed)
                    } else {
                        addToArray(fresh, suiteName2, failed)
                    }
                }
            }
        } else {
            testsObj2.passed.forEach(name => addToArray(fresh, suiteName2, name))
            testsObj2.failed.forEach(name => addToArray(fresh, suiteName2, name))
        }
    }
    for (const [suiteName1, testsObj1] of Object.entries(report1)) {
        testsObj1.passed.forEach(name => addToArray(old, suiteName1, name))
        testsObj1.failed.forEach(name => addToArray(old, suiteName1, name))
    }

    console.info(`OLD ${count(old)}`)
    printInfo(old)
    console.info(`\nNEW ${count(fresh)}`)
    printInfo(fresh)
    console.info(`\nPROGRESS ${count(progress)}`)
    printInfo(progress)
    console.info(`\nREGRESS ${count(regress)}`)
    printInfo(regress)
}

function parseReport(reportContent) {
  const suitesMap = {}
  let currentSuite = null
  const lines = reportContent.split('\n')
  for (const line of lines) {
    if (line.startsWith('SUITE:')) {
      const suiteMatch = line.match(/\[.*?\]\s+(.+)/)
      if (suiteMatch) {
        currentSuite = suiteMatch[1].trim()
        suitesMap[currentSuite] = { passed: [], failed: [] }
      }
    } else if (currentSuite && line) {
      const statusMatch = line.match(/^(\w+)\s+(PASS|FAIL|ERROR)/)
      if (statusMatch) {
        switch (statusMatch[2]) {
            case 'PASS':
                suitesMap[currentSuite].passed.push(statusMatch[1])
                break
            case 'FAIL':
            case 'ERROR':
                suitesMap[currentSuite].failed.push(statusMatch[1])
                break
        }
      }
    }
  }
  return suitesMap
}

function addToArray(object, field, value) {
    if (Array.isArray(object[field])) {
        object[field].push(value)
    } else {
        object[field] = [value]
    }
}

function count(obj) {
    let counter = 0
    Object.entries(obj).forEach(entries => counter += entries[1].length)
    return counter
}

function printInfo(obj) {
    const entries = Object.entries(obj)
    if (entries.length === 0) {
        console.info('    none')
    } else {
        for (const [suiteName, tests] of entries) {
            console.info(`  SUITE: ${suiteName}`)
            tests.sort().forEach(test => console.info(`         ${test}`))
        }
    }
}
